# -*- coding: utf-8 -*-
import frappe
from frappe.model.document import Document
from frappe.utils import today, now, cstr, flt
import json

class ScrapReceipt(Document):
    """
    余料入库单控制器类
    管理余料入库的业务流程和状态变更
    """
    
    def validate(self):
        """验证数据有效性"""
        self.validate_unique_receipt_id()
        self.validate_warehouse()
        self.validate_scrap_materials()
        self.calculate_total_quantity()
    
    def before_save(self):
        """保存前处理"""
        self.set_receipt_date()
    
    def on_submit(self):
        """提交后处理"""
        self.update_scrap_material_status()
        self.create_transaction_log()
    
    def on_cancel(self):
        """取消后处理"""
        self.revert_scrap_material_status()
        self.create_cancel_log()
    
    def validate_unique_receipt_id(self):
        """验证入库单编号唯一性"""
        if self.receipt_id:
            exists = frappe.db.exists("Scrap Receipt", {
                "receipt_id": self.receipt_id,
                "name": ["!=", self.name]
            })
            if exists:
                frappe.throw(f"入库单编号 {self.receipt_id} 已存在，请使用其他编号")
    
    def validate_warehouse(self):
        """验证仓库有效性"""
        if self.warehouse:
            warehouse_doc = frappe.get_doc("Scrap Warehouse", self.warehouse)
            if warehouse_doc.status != "启用":
                frappe.throw(f"仓库 {self.warehouse} 未启用，无法进行入库操作")
    
    def validate_scrap_materials(self):
        """验证余料列表"""
        if not self.scrap_materials or len(self.scrap_materials) == 0:
            frappe.throw("入库单必须包含至少一个余料项")
        
        # 检查是否有重复的余料
        scrap_materials = [item.scrap_material for item in self.scrap_materials]
        if len(scrap_materials) != len(set(scrap_materials)):
            frappe.throw("入库单中存在重复的余料项")
        
        # 验证每个余料项
        for item in self.scrap_materials:
            if not item.scrap_material:
                frappe.throw("余料项必须选择余料")
            
            if not item.location:
                frappe.throw(f"余料 {item.scrap_material} 必须选择库位")
            
            if flt(item.quantity) <= 0:
                frappe.throw(f"余料 {item.scrap_material} 的数量必须大于0")
            
            # 检查余料是否已经入库
            existing_receipt = frappe.db.exists("Scrap Receipt", {
                "docstatus": 1,
                "scrap_materials": {"scrap_material": item.scrap_material}
            })
            if existing_receipt:
                frappe.throw(f"余料 {item.scrap_material} 已经在其他入库单中入库")
    
    def calculate_total_quantity(self):
        """计算总数量"""
        total = 0
        for item in self.scrap_materials:
            total += flt(item.quantity)
        self.total_quantity = total
    
    def set_receipt_date(self):
        """设置入库日期"""
        if not self.receipt_date:
            self.receipt_date = today()
    
    def update_scrap_material_status(self):
        """更新余料状态"""
        for item in self.scrap_materials:
            # 更新余料的库位和状态
            material_doc = frappe.get_doc("Scrap Material", item.scrap_material)
            material_doc.location = item.location
            material_doc.status = "可用"
            material_doc.save(ignore_permissions=True)
    
    def create_transaction_log(self):
        """创建事务日志"""
        log_doc = frappe.get_doc({
            "doctype": "Comment",
            "comment_type": "Info",
            "reference_doctype": self.doctype,
            "reference_name": self.name,
            "comment_email": frappe.session.user,
            "content": f"余料入库单已提交，共入库 {len(self.scrap_materials)} 项余料"
        })
        log_doc.insert(ignore_permissions=True)
    
    def revert_scrap_material_status(self):
        """恢复余料状态"""
        for item in self.scrap_materials:
            # 恢复余料的原始状态
            material_doc = frappe.get_doc("Scrap Material", item.scrap_material)
            # 这里应该恢复到入库前的状态，但为了简化，我们只恢复库位为空
            # 实际应用中应该记录原始状态并恢复
            material_doc.location = ""
            material_doc.save(ignore_permissions=True)
    
    def create_cancel_log(self):
        """创建取消日志"""
        log_doc = frappe.get_doc({
            "doctype": "Comment",
            "comment_type": "Info",
            "reference_doctype": self.doctype,
            "reference_name": self.name,
            "comment_email": frappe.session.user,
            "content": f"余料入库单已取消，共取消 {len(self.scrap_materials)} 项余料"
        })
        log_doc.insert(ignore_permissions=True)
    
    def submit_for_approval(self):
        """提交审批"""
        if self.status != "草稿":
            frappe.throw("只有草稿状态的入库单可以提交审批")
        
        self.status = "待审核"
        self.submitted_by = frappe.session.user
        self.submitted_date = now()
        self.save(ignore_permissions=True)
        
        # 发送通知给审批人
        self.send_approval_notification()
    
    def approve(self, approve=True):
        """审批"""
        if self.status != "待审核":
            frappe.throw("只有待审核状态的入库单可以进行审批")
        
        if approve:
            self.status = "已审核"
            # 审批通过后自动提交
            self.submit()
        else:
            self.status = "已拒绝"
            self.save(ignore_permissions=True)
        
        self.approved_by = frappe.session.user
        self.approved_date = now()
        self.save(ignore_permissions=True)
        
        # 发送通知给提交人
        self.send_approval_result_notification(approve)
    
    def send_approval_notification(self):
        """发送审批通知"""
        # 获取Scrap Manager角色的用户
        managers = frappe.get_all("Has Role", {
            "role": "Scrap Manager"
        }, pluck="parent")
        
        if managers:
            for manager in managers:
                notification_doc = frappe.get_doc({
                    "doctype": "Notification Log",
                    "for_user": manager,
                    "type": "Alert",
                    "document_type": self.doctype,
                    "document_name": self.name,
                    "subject": f"余料入库单 {self.receipt_id} 待审批",
                    "email_content": f"余料入库单 {self.receipt_id} 已提交审批，请及时处理。"
                })
                notification_doc.insert(ignore_permissions=True)
    
    def send_approval_result_notification(self, approved):
        """发送审批结果通知"""
        if self.submitted_by:
            status_text = "通过" if approved else "拒绝"
            notification_doc = frappe.get_doc({
                "doctype": "Notification Log",
                "for_user": self.submitted_by,
                "type": "Alert",
                "document_type": self.doctype,
                "document_name": self.name,
                "subject": f"余料入库单 {self.receipt_id} 审批{status_text}",
                "email_content": f"余料入库单 {self.receipt_id} 已被审批{status_text}。"
            })
            notification_doc.insert(ignore_permissions=True)
    
    @staticmethod
    def get_receipt_list(filters=None):
        """获取入库单列表"""
        if not filters:
            filters = {}
        
        return frappe.get_all("Scrap Receipt",
                            filters=filters,
                            fields=["name", "receipt_id", "receipt_date", "warehouse", 
                                   "status", "total_quantity", "submitted_by", "approved_by"],
                            order_by="receipt_date desc")
    
    @staticmethod
    def get_pending_approvals():
        """获取待审批的入库单"""
        return frappe.get_all("Scrap Receipt",
                            filters={"status": "待审核"},
                            fields=["name", "receipt_id", "receipt_date", "warehouse", 
                                   "total_quantity", "submitted_by", "submitted_date"],
                            order_by="submitted_date asc")